package ru.st.selenium.helpers;

import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;

import java.util.List;

public class MovieCollectionHelper {

    private WebDriver driver;
    private boolean acceptNextAlert = true;

    public MovieCollectionHelper(WebDriver driver) {
        this.driver = driver;
    }

    public void logIn(String username, String password) {
        WebElement usernameField = driver.findElement(By.id("username"));
        usernameField.clear();
        usernameField.sendKeys(username);

        WebElement passwordField = driver.findElement(By.name("password"));
        passwordField.clear();
        passwordField.sendKeys(password);

        driver.findElement(By.name("submit")).click();

        (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return isElementPresent(By.linkText("Log out"));
            }
        });
//        Assert.assertFalse(isElementPresent(By.name("submit")));
    }

    public void logOut() {
        driver.findElement(By.linkText("Log out")).click();
        Assert.assertTrue(closeAlertAndGetItsText().matches("^Are you sure you want to log out[\\s\\S]$"));
        (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return isElementPresent(By.name("submit"));
            }
        });
//        Assert.assertFalse(isElementPresent(By.linkText("Log out")));
    }

    private String closeAlertAndGetItsText() {
        try {
            Alert alert = driver.switchTo().alert();
            String alertText = alert.getText();
            if (acceptNextAlert) {
                alert.accept();
            } else {
                alert.dismiss();
            }
            return alertText;
        } finally {
            acceptNextAlert = true;
        }
    }

    public void clickAddMovieButton() {
        driver.findElement(By.linkText("Add movie")).click();
    }

    public void populateMovieDetails(String imdbNumber, String title, String aka, String year, String duration,
                                     String rating, String format, boolean ownMovie, boolean seenMovie, boolean loanedMovie,
                                     String coverPath, String trailerURL, String personalNotes, String taglines,
                                     String plotOutline, String plots, String languages, String subtitles, String audio,
                                     String video, String country, String genres, String director, String writer,
                                     String producer, String music, String cast) {

        if (imdbNumber != null) {
            WebElement imdbField = driver.findElement(By.name("imdbid"));
            imdbField.clear();
            imdbField.sendKeys(imdbNumber);

        }

        if (title != null) {
            WebElement titleField = driver.findElement(By.name("name"));
            titleField.clear();
            titleField.sendKeys(title);
        }

        if (aka != null) {
            WebElement akaField = driver.findElement(By.name("aka"));
            akaField.clear();
            akaField.sendKeys(aka);
        }

        if (year != null) {
            WebElement yearField = driver.findElement(By.name("year"));
            yearField.clear();
            yearField.sendKeys(year);
        }

        if (duration != null) {
            WebElement durationField = driver.findElement(By.name("duration"));
            durationField.clear();
            durationField.sendKeys(duration);
        }

        if (rating != null) {
            WebElement ratingField = driver.findElement(By.name("rating"));
            ratingField.clear();
            ratingField.sendKeys(rating);

        }

        if (format != null) {
            WebElement formatField = driver.findElement(By.name("format"));
            formatField.clear();
            formatField.sendKeys(format);
        }

        if (ownMovie) {
            driver.findElement(By.id("own_yes")).click();
        } else {
            driver.findElement(By.id("own_no")).click();
        }

        if (seenMovie) {
            driver.findElement(By.id("seen_yes")).click();
        } else {
            driver.findElement(By.id("seen_no")).click();
        }

        if (loanedMovie) {
            driver.findElement(By.id("loaned_yes")).click();
        } else {
            driver.findElement(By.id("loaned_no")).click();
        }

        if (coverPath != null) {
            WebElement coverField = driver.findElement(By.name("cover"));
            coverField.clear();
            coverField.sendKeys(coverPath);
        }

        if (trailerURL != null) {
            WebElement trailerField = driver.findElement(By.name("trailer"));
            trailerField.clear();
            trailerField.sendKeys(trailerURL);
        }

        if (personalNotes != null) {
            WebElement notesField = driver.findElement(By.name("notes"));
            notesField.clear();
            notesField.sendKeys(personalNotes);
        }

        if (taglines != null) {
            WebElement taglinesField = driver.findElement(By.name("taglines"));
            taglinesField.clear();
            taglinesField.sendKeys(taglines);
        }

        if (plotOutline != null) {
            WebElement plotOutlineField = driver.findElement(By.name("plotoutline"));
            plotOutlineField.clear();
            plotOutlineField.sendKeys(plotOutline);
        }

        if (plots != null) {
            WebElement plotsField = driver.findElement(By.name("plots"));
            plotsField.clear();
            plotsField.sendKeys(plots);
        }

        if (languages != null) {
            WebElement languagesField = driver.findElement(By.name("languages"));
            languagesField.clear();
            languagesField.sendKeys(languages);
        }

        if (subtitles != null) {
            WebElement subtitlesField = driver.findElement(By.name("subtitles"));
            subtitlesField.clear();
            subtitlesField.sendKeys(subtitles);
        }

        if (audio != null) {
            WebElement audioField = driver.findElement(By.name("audio"));
            audioField.clear();
            audioField.sendKeys(audio);
        }

        if (video != null) {
            WebElement videoField = driver.findElement(By.name("video"));
            videoField.clear();
            videoField.sendKeys(video);
        }

        if (country != null) {
            WebElement countryField = driver.findElement(By.name("country"));
            countryField.clear();
            countryField.sendKeys(country);
        }

        if (genres != null) {
            WebElement genresField = driver.findElement(By.name("genres"));
            genresField.clear();
            genresField.sendKeys(genres);
        }

        if (director != null) {
            WebElement directorField = driver.findElement(By.name("director"));
            directorField.clear();
            directorField.sendKeys(director);
        }

        if (writer != null) {
            WebElement writerField = driver.findElement(By.name("writer"));
            writerField.clear();
            writerField.sendKeys(writer);
        }

        if (producer != null) {
            WebElement producerField = driver.findElement(By.name("producer"));
            producerField.clear();
            producerField.sendKeys(producer);
        }

        if (music != null) {
            WebElement musicField = driver.findElement(By.name("music"));
            musicField.clear();
            musicField.sendKeys(music);
        }

        if (cast != null) {
            WebElement castField = driver.findElement(By.name("cast"));
            castField.clear();
            castField.sendKeys(cast);
        }
    }

    public void submitMovieAndAssertIsSaved(String title, String year) {
        driver.findElement(By.id("submit")).click();

        (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return d.findElement(By.className("maininfo_full")).isEnabled();
            }
        });

        WebElement movieTitleAfterSaving = driver.findElement(By.xpath("//div[@class = 'maininfo_full']/h2"));
        Assert.assertEquals(movieTitleAfterSaving.getText(), title + " (" + year + ")");
    }

    public void submitMovieAndAssertError() {
        driver.findElement(By.id("submit")).click();
        boolean isFieldRequiredDisplayed = isElementPresent(By.className("error"));
        Assert.assertTrue(isFieldRequiredDisplayed);
    }

    private boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public boolean checkIfAnyMovieExists() {
        List<WebElement> webElements = driver.findElements(By.xpath("//div[@id = 'results']/a/div"));
        return webElements.size() > 0;
    }

    public void removeMovie() {
        int countMoviesBefore = driver.findElements(By.xpath("//div[@id = 'results']/a/div")).size();
        WebElement movie = driver.findElement(By.xpath("//div[@id = 'results']/a/div"));

        driver.findElement(By.id(movie.getAttribute("id"))).click();
        driver.findElement(By.linkText("Remove")).click();
        Assert.assertTrue(closeAlertAndGetItsText().matches("^Are you sure you want to remove this[\\s\\S]$"));

        waitUntil(By.id("results"));

        int countMoviesAfter = driver.findElements(By.xpath("//div[@id = 'results']/a/div")).size();
        Assert.assertTrue(countMoviesBefore > countMoviesAfter);
    }

    public void navigateToHomePage() {
        driver.findElement(By.linkText("Home")).click();
        waitUntil(By.id("results"));
    }

    public void clearSearchField() {
        WebElement searchField = driver.findElement(By.id("q"));

        searchField.clear();
        /*
        searchField.sendKeys(Keys.CONTROL + "a");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        searchField.sendKeys(Keys.DELETE);
        */
        searchField.sendKeys(Keys.ENTER);
    }

    public String getFirstMovieTitle() {
        WebElement movieTitle = driver.findElement(By.xpath("//div[@id = 'results']/a/div/div[@class = 'title']"));
        System.out.println("Movie to be searched: " + movieTitle.getText());
        return movieTitle.getText();
    }

    public void searchMovie(String movieTitle) {
        WebElement searchField = driver.findElement(By.id("q"));
        searchField.clear();
        searchField.sendKeys(movieTitle);
        searchField.sendKeys(Keys.ENTER);

        waitUntil(By.id("results"));
    }

    public void searchMovieNoResults(String movieTitle) {
        WebElement searchField = driver.findElement(By.id("q"));
        searchField.clear();
        searchField.sendKeys(movieTitle);
        searchField.sendKeys(Keys.ENTER);

        waitUntil(By.className("content"));
    }

    public void assertMovieFound(String expectedMovieTitle) {
        WebElement movieFound = driver.findElement(By.xpath("//div[@id = 'results']/a/div/div[@class = 'title']"));

        Assert.assertEquals(movieFound.getText(), expectedMovieTitle);
    }

    public void assertMovieNotFound() {
        boolean resultsFound = checkIfAnyMovieExists();
        Assert.assertFalse(resultsFound);

        WebElement results = driver.findElement(By.className("content"));

        Assert.assertEquals("No movies where found.", results.getText());
    }

    public void waitUntilResultsAreDisplayed() {
        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return d.findElement(By.id("results")).isDisplayed();
            }
        });
    }

    public void waitUntil(final By by) {
        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return d.findElement(by).isDisplayed();
            }
        });
    }

}
